// LoopInfo.cpp
// Implementation of methods for class LoopInfo

#include <llvm/ADT/APSInt.h>
#include <llvm/Support/raw_ostream.h>
#include <clang/Rewrite/Rewriter.h>
#include <clang/AST/Stmt.h>
#include "SubscriptExpr.h"
#include "LoopInfo.h"

// search for the index of a variable by name.
//  since we are assuming only one variable, this won't be used.
int LoopNestInfo::getIndex(std::string varname) {
    std::vector<InductionVarInfo>::iterator pos;
    for (pos = this->begin(); pos < this->end(); pos++) {
        if (pos->name == varname)
            return pos - this->begin() + 1;  // 0 is reserved for the constant.
    }
    return -1;
}

/** Add a statement reference to the loop info */
void LoopNestInfo::addStmt(clang::Stmt* stmt) {
    statements.push_back(stmt);
}
    
void LoopNestInfo::addStmtLoc(clang::SourceLocation loc) {
    stmtLocs.push_back(loc);
}

// this one too.
void LoopNestInfo::setRewriter(clang::Rewriter rw, clang::FileID fid) {
    rewriter = rw; mainFileID = fid;
}
        
void LoopNestInfo::insertStatementComment(int stmtIndex, std::string comment) {
    rewriter.InsertTextBefore(stmtLocs.at(stmtIndex), "/* " + comment + " */ ");
}

void LoopNestInfo::replaceStmt(int oldstmt, int newstmt) {
    rewriter.ReplaceStmt(statements[oldstmt], statements[newstmt]);
}

int LoopNestInfo::nStatements() { return stmtLocs.size(); }

// access methods for the bounds of the outermost induction variable.
llvm::APSInt LoopNestInfo::lbound() { return (*this)[0].lbound; }
llvm::APSInt LoopNestInfo::ubound() { return (*this)[0].ubound; }

void LoopNestInfo::writeSource(llvm::raw_ostream* outfile) {
    // Get the buffer corresponding to MainFileID.
    // If we haven't changed it, then we are done.
    const clang::RewriteBuffer* rewriteBuf = rewriter.getRewriteBufferFor(mainFileID);
    if (rewriteBuf) {
        llvm::outs() << "Source file rewritten.\n";
        *outfile << std::string(rewriteBuf->begin(), rewriteBuf->end());
    } else {
        llvm::outs() << "Source file unchanged.\n";
    }
    outfile->flush();
}
    

